package com.xiongkf.blockchain.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.java_websocket.WebSocket;
import com.alibaba.fastjson.JSON;
import com.xiongkf.blockchain.pojo.Block;
import com.xiongkf.blockchain.pojo.BlockChain;
import com.xiongkf.blockchain.service.P2PService;

/**
 * http服务类
 * 
 * @author bear.xiong
 */
public class HttpServer {
	// 区块链服务
	private BlockChain blockChain;

	// P2P服务
	private P2PService p2pService;

	// 构造函数初始化
	public HttpServer(BlockChain blockChain, P2PService p2pService) {
		this.blockChain = blockChain;
		this.p2pService = p2pService;
	}

	// 初始化服务端口
	public void initHTTPServer(int port) {
		try {
			Server server = new Server(port);
			System.out.println("listening http port on: " + port);
			ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
			context.setContextPath("/blockchain/");
			server.setHandler(context);
			context.addServlet(new ServletHolder(new BlocksServlet()), "/blocks");
			context.addServlet(new ServletHolder(new MineBlockServlet()), "/mine");
			context.addServlet(new ServletHolder(new PeersServlet()), "/peers");
			context.addServlet(new ServletHolder(new AddPeerServlet()), "/addPeer");
			server.start();
			server.join();
		} catch (Exception e) {
			System.out.println("init http server is error:" + e.getMessage());
		}
	}

	// 查询区块链Servlet
	private class BlocksServlet extends HttpServlet {
		private static final long serialVersionUID = -4932614018162930265L;

		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			resp.setCharacterEncoding("UTF-8");
			List<Block> list = blockChain.getBlockChain();
			for (Block block : list) {
				resp.getWriter().println(JSON.toJSONString(block));
			}
		}
	}

	// 挖矿Servlet
	private class MineBlockServlet extends HttpServlet {
		private static final long serialVersionUID = -136404810502842741L;

		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			this.doPost(req, resp);
		}

		@Override
		protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			resp.setCharacterEncoding("UTF-8");
			String data = req.getParameter("data");
			Block newBlock = blockChain.generateNextBlock(data);
			blockChain.addBlock(newBlock);
			p2pService.broatcast(p2pService.responseLatestMessage());
			String result = JSON.toJSONString(newBlock);
			resp.getWriter().print(result);
		}
	}

	// 添加节点Servlet
	private class AddPeerServlet extends HttpServlet {
		private static final long serialVersionUID = -3070905868072646007L;

		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			this.doPost(req, resp);
		}

		@Override
		protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			resp.setCharacterEncoding("UTF-8");
			String peer = req.getParameter("peer");// peer=ws://127.0.0.1:7001
			// 节点去重的逻辑，避免重复添加
			String hostAdd = peer.split(":")[1].split("//")[1];
			for (WebSocket socket : p2pService.getSockets()) {
				InetSocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
				if (remoteSocketAddress.getHostName() == hostAdd) {
					resp.getWriter().print("is aready connect");
				}
			}

			p2pService.connectToPeer(peer);
			resp.getWriter().print(JSON.toJSONString("success"));
		}
	}

	// 查询节点Servlet
	private class PeersServlet extends HttpServlet {
		private static final long serialVersionUID = -2702283153702080719L;

		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			resp.setCharacterEncoding("UTF-8");
			List<Map<String, String>> wsList = new ArrayList<Map<String, String>>();

			for (WebSocket socket : p2pService.getSockets()) {
				InetSocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
				Map<String, String> wsMap = new HashMap<String, String>();
				wsMap.put("remoteHost", remoteSocketAddress.getHostName());
				wsMap.put("remotePort", remoteSocketAddress.getPort() + "");
				wsList.add(wsMap);
				// resp.getWriter().print(remoteSocketAddress.getHostName() + ":" + remoteSocketAddress.getPort());
			}

			resp.getWriter().print(JSON.toJSONString(wsList));
		}
	}

	public static void main(String[] args) {
		BlockChain blockChain = new BlockChain();
		P2PService p2pService = new P2PService(blockChain);
		p2pService.initP2PServer(7001);
		HttpServer hs = new HttpServer(blockChain, p2pService);
		hs.initHTTPServer(8080);
	}
}
